package com.ms.demo.validator;

import cn.hutool.core.net.Ipv4Util;
import com.ms.demo.utils.IpUtils;
import com.ms.demo.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * <p>Project:demo-NoRepeatSubmitAop
 * <p>Powered by ms on 2023-01-30 22:37:42
 *
 * @author ms
 * @version 1.0
 * @since 1.8
 */
@Slf4j
@Aspect
@Component
public class NoRepeatSubmitAop {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /*
    环绕通知
     */
    @Around("execution(* com.ms.*.controller.*Controller.*(..))&& @annotation(noRepeatSubmit)")
    public Object doAround(ProceedingJoinPoint pjp, NoRepeatSubmit noRepeatSubmit) {
        try {
            HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
            String ip = IpUtils.getIpAdrress(request);
            //String url = request.getRequestURL().toString();
            //现在时间
            long now = System.currentTimeMillis();

            String key = "REQUEST_FORM_" + ip;
            if (Boolean.TRUE.equals(redisTemplate.hasKey(key))) {
                //获取上次提交时间
                long last = Long.parseLong(Objects.requireNonNull(redisTemplate.opsForValue().get(key)));
                //不重复提交
                if ((now - last) > noRepeatSubmit.time()) {
                    redisTemplate.opsForValue().set(key, String.valueOf(now), 10, TimeUnit.SECONDS);
                    return pjp.proceed();
                } else {
                    return R.error().message("请勿频繁操作！");
                }
            }
            //第一次提交表单
            else {
                redisTemplate.opsForValue().set(key, String.valueOf(now), 10, TimeUnit.SECONDS);//10秒过期
                //放行
                return pjp.proceed();
            }
        } catch (Throwable throwable) {
            log.error("校验表单是否重复提交时异常：{}", throwable.getMessage());
            return R.error().message("校验表单是否重复提交时异常");
        }
    }

}
